<template>
  <div class="content">
    <grid-layout
      v-if="components.length > 0"
      :layout.sync="layout"
      :col-num="24"
      :row-height="30"
      :is-draggable="false"
      :is-resizable="false"
      :is-mirrored="false"
      :vertical-compact="false"
      :margin="[grid.horizontal, grid.vertical]"
      :use-css-transforms="true"
    >
      <grid-item
        v-for="(item,index) in layout"
        :x="item.x"
        :y="item.y"
        :w="item.w"
        :h="item.h"
        :i="item.i"
        :key="item.i"
        :ref="components[index].id+'_grid'"
        :style="components[index].style"
      >
        <component
          :is="components[index].name"
          :data="components[index]"
          :file="files.current"
          :index="index"
          :view="false"
          :ref="components[index].id"
          @updateResult="updateResult"
          :pageType="pageType"
        ></component>
      </grid-item>
    </grid-layout>
  </div>
</template>

<script>
import { mapState, mapActions } from 'vuex';
import VueGridLayout from 'vue-grid-layout';

import textItem from '@/pages/Mark/Middle/Basic/TextItem';
import inputItem from '@/pages/Mark/Middle/Basic/InputItem';
import selectItem from '@/pages/Mark/Middle/Basic/SelectItem';
import switchItem from '@/pages/Mark/Middle/Basic/SwitchItem';
import datepickerItem from '@/pages/Mark/Middle/Basic/DatepickerItem';
import buttonItem from '@/pages/Mark/Middle/Basic/ButtonItem';
import checkboxItem from '@/pages/Mark/Middle/Basic/CheckboxItem';
import radioItem from '@/pages/Mark/Middle/Basic/RadioItem';
import checkboxgroupItem from '@/pages/Mark/Middle/Basic/CheckboxgroupItem';
import radiogroupItem from '@/pages/Mark/Middle/Basic/RadiogroupItem';
import rateItem from '@/pages/Mark/Middle/Basic/RateItem';
import tableItem from '@/pages/Mark/Middle/Basic/TableItem';
import delimitItem from '@/pages/Mark/Middle/Senior/DelimitItem';
import sectionItem from '@/pages/Mark/Middle/Senior/SectionItem';

export default {
  name: 'MarkContent',
  props: ['files', 'pageType'],
  data () {
    return {
    }
  },
  created () {
    this.$on('saveBefore', this.saveBefore)
  },
  mounted () {

  },
  computed: {
    ...mapState({
      layout: state => state.mark.layout,
      components: state => state.mark.components,
      grid: state => state.mark.grid
    })
  },
  methods: {
    ...mapActions(['changeActiveCom']),
    saveBefore () {
      let components = this.components
      let result = {} // 保存的数据
      for (let i = 0; i < components.length; i++) {
        let component = components[i]
        // 先校验
        if (!this.checkComponentValue(component)) return;

        result[component.id] = {
          value: component.value
        }
      }

      // 将保存的结果调换files.current.result
      this.files.current.result = result
    },
    checkComponentValue (component) {
      let defaultMsg = {
        required: '内容不能为空',
        strMin: '长度不能少于',
        numMin: '数值不能小于',
        strMax: '长度不能大于',
        numMax: '数值不能大于',
        type: '数据类型错误',
        pattern: '内容不符合要求'
      }
      let { valid, value, componentType } = component
      if (componentType === 0) { // 基础组件
        let validType = Object.prototype.toString.call(valid).slice(8, -1).toLowerCase()
        if (validType === 'array') { // 只有数组类型才进行校验 这里只处理定义好的规则校验； 不符合我们定义规则的 不做任何处理
          for (let i = 0; i < valid.length; i++) {
            let valids = valid[i]
            if (valids.required !== undefined && !value) {
              this.$Message.warning(valids.message || defaultMsg.required);// 校验是否必填
              return false;
            }
            if (valids.type !== undefined && Object.prototype.toString.call(value).slice(8, -1).toLowerCase() !== valids.type) { // [object Array]
              this.$Message.warning(valids.message || defaultMsg.type); // 校验value数据 类型
              return false;
            }
            if (valids.min !== undefined && (typeof value === 'string' || typeof value === 'number')) { // 数字 字符串两种类型
              if (typeof value === 'string' && value.length < valids.min) {
                this.$Message.warning(valids.message || defaultMsg.strMin + valids.min + '字符');
                return false;
              }
              if (typeof value === 'number' && value < valids.min) {
                this.$Message.warning(valids.message || defaultMsg.numMin + valids);
                return false;
              }
            }
            if (valids.max !== undefined && (typeof value === 'string' || typeof value === 'number')) {
              if (typeof value === 'string' && value.length > valids.max) {
                this.$Message.warning(valids.message || defaultMsg.strMax + valids.max + '字符');
                return false;
              }
              if (typeof value === 'number' && value > valids.max) {
                this.$Message.warning(valids.message || defaultMsg.numMax + valids);
                return false;
              }
            }
            if (valids.pattern !== undefined && !RegExp(valids).test(value)) {
              this.$Message.warning(valids.message || defaultMsg.pattern);
              return false;
            }
          }
        }
      } else if (componentType === 1) { // 高级组件
        if (Object.prototype.toString.call(this.$refs[component.id].validate).slice(8, -1).toLowerCase() === 'function' && !this.$refs[component.id].validate()) {
          return false;
        }
      }
      this.$parent.saveCheckType = 1; // 校验成功
      return true;
    },
    // 更新结果
    updateResult (data) {
      let item = this.components[data.index];
      item.value = data.value;

      // 更新结果
      this.changeActiveCom(item)
    }
  },
  components: {
    textItem,
    inputItem,
    switchItem,
    selectItem,
    datepickerItem,
    buttonItem,
    checkboxItem,
    radioItem,
    checkboxgroupItem,
    radiogroupItem,
    rateItem,
    tableItem,
    delimitItem,
    sectionItem,
    GridLayout: VueGridLayout.GridLayout,
    GridItem: VueGridLayout.GridItem
  }
}
</script>

<style lang="less" scoped>
.content {
  position: fixed;
  left: 0;
  top: 100px;
  bottom: 0px;
  right: 0px;
  z-index: 999;
  background: #fff;
}
.flex_box {
  display: flex;
  flex-direction: row;
  flex-wrap: nowrap;
}
.flex_auto {
  flex: 1;
}
</style>
